微信开发 - 快速入门

微信是一个生活方式,张小龙提出的这个愿景已经得到了越来越清晰的体现。

群聊、语音、视频,照片/视频/位置共享,支付和商店都有了,还能通过公众账号来获取各种资源……

如今的微信就是在日中天的状态,公众平台带来的影响有目共睹,所以很多公司和个人都希望有自己的公众号,想充分利用却无处下手,下面我们分为几篇文章,由浅入深的了解微信开发。

在下面的学习中,需要你具有PHP语言的基础,并拥有一台具有PHP运行环境的主机,如果还没有可以通过新浪SAE,阿里云ECS等进行搭建。

下面进入正题!

接入开发者模式

接入开发者模式非常简单,主要分下面几个步骤:

  1. 下载官方接口文件;
  2. 简单调整接口文件的代码;
  3. 将调整好的接口文件上传到服务器;
  4. 在开发者后台进行接口的验证;

首先下载PHP接口文件,下载地址请点击微信公众平台开发者文档

将原有的代码:

1
2
3
define("TOKEN", "weixin");
$wechatObj = new wechatCallbackapiTest();
$wechatObj->valid();

修改为:

1
2
3
4
5
6
7
8
9
10
define("TOKEN", "wechat");
$wechatObj = new wechatCallbackapiTest();
if ($_GET["echostr"]) {
$wechatObj->valid();
}
else {
$wechatObj->responseMsg();
}

然后将修改后的PHP文件上传至你的服务器,进入:

微信公众平台 > 开发 > 基本配置 > 服务器配置 > 修改配置

在弹出的基本配置/ 填写服务器配置中:

URL填写你的PHP文件地址,如:https://localhost/filepath/wx_sample.php

Token填写你在PHP文件中设定的值,如:define("TOKEN", "wechat");,填写wechat

EncodingAESKey使用随机生成即可;

消息加解密方式选择明文模式即可;

点击提交,就完成了开发者模式的接入。

开发者模式下数据传输及处理

微信开发模式数据传输

了解开发者模式下的数据传输后,我们开始编写第一个程序。

Hello World

没错,就是从它开始……

实现Hello World非常简单,首先编写程序代码,将PHP文件中原代码:

1
2
3
4
5
6
7
8
if(!empty( $keyword )) {
$msgType = "text";
$contentStr = "Welcome to wechat world!";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo "Input something...";
}

修改为:

1
2
3
4
5
6
7
8
if(!empty( $keyword )) {
$msgType = "text";
$contentStr = $keyword."World";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo "Input something...";
}

此时,向你的公众号发送一个Hello,就会返回一个Hello World,相信大家都已经明白,$keyword这个变量,就是用户发送的文本信息

这时当用户发送语音,图片,位置等信息时,因为PHP文件对此没有进行对应的处理,所以用户设备会收到该公众号暂时无法提供服务,请稍后再试

被动回复消息

当用户发送消息给公众号时(或某些特定的用户操作引发的事件推送时),会产生一个POST请求,开发者可以在响应包(Get)中返回特定XML结构,来对该消息进行响应(现支持回复文本、图片、图文、语音、视频、音乐)。严格来说,发送被动响应消息其实并不是一种接口,而是对微信服务器发过来消息的一次回复。

一旦遇到以下情况,微信都会在公众号会话中,向用户下发系统提示“该公众号暂时无法提供服务,请稍后再试”:

1、开发者在5秒内未回复任何内容

2、开发者回复了异常数据,比如JSON数据等

另外,请注意,回复图片等多媒体消息时需要预先通过素材管理接口上传临时素材到微信服务器,可以使用素材管理中的临时素材,也可以使用永久素材。

被动回复支持的消息类型有:

文本、图片、语音、视频、音乐

当然,还有可以包括以上所有类型的图文消息

各消息类型是由XML数据包构成,关于数据包的格式请访问微信开发者文档

关注事件处理

用户在关注与取消关注公众号时,微信会把这个事件推送到开发者填写的URL。方便开发者给用户下发欢迎消息或者做帐号的解绑。

关注事件实际上是获取Event事件类型,并设置不同消息类型的XML数据包推送到用户设备

推送XML数据包示例:

1
2
3
4
5
6
7
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[FromUser]]></FromUserName>
<CreateTime>123456789</CreateTime>
<MsgType><![CDATA[event]]></MsgType>
<Event><![CDATA[subscribe]]></Event>
</xml>

参数说明:

参数 描述
ToUserName 开发者微信号
FromUserName 发送方帐号(一个OpenID)
CreateTime 消息创建时间 (整型)
MsgType 消息类型,event
Event 事件类型,subscribe(订阅)、unsubscribe(取消订阅)

关注事件文字回复

首先我们需要获取Event参数,并对Event进行相应的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
$postObj = simplexml_load_string($postStr, 'SimpleXMLElement', LIBXML_NOCDATA);
$fromUsername = $postObj->FromUserName;
$toUsername = $postObj->ToUserName;
$keyword = trim($postObj->Content);
$event = $postObj->Event;
$time = time();
$textTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<Content><![CDATA[%s]]></Content>
<FuncFlag>0</FuncFlag>
</xml>";
if ($event == "subscribe") {
echo "订阅事件";
$msgType = "text";
$contentStr = "欢迎关注superliar";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
elseif ($event == "unsubscribe") {
echo "取消订阅事件";
}

这时我们取消关注的公众号,再重新关注它,会收到:

1
欢迎关注superliar

关注事件图文回复

图文消息的XML包结构如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<xml>
<ToUserName><![CDATA[toUser]]></ToUserName>
<FromUserName><![CDATA[fromUser]]></FromUserName>
<CreateTime>12345678</CreateTime>
<MsgType><![CDATA[news]]></MsgType>
<ArticleCount>2</ArticleCount>
<Articles>
<item>
<Title><![CDATA[title1]]></Title>
<Description><![CDATA[description1]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
<item>
<Title><![CDATA[title]]></Title>
<Description><![CDATA[description]]></Description>
<PicUrl><![CDATA[picurl]]></PicUrl>
<Url><![CDATA[url]]></Url>
</item>
</Articles>
</xml>

参数说明如下:

参数 是否必须 说明
ToUserName 接收方帐号(收到的OpenID)
FromUserName 开发者微信号
CreateTime 消息创建时间 (整型)
MsgType news
ArticleCount 图文消息个数,限制为10条以内
Articles 多条图文消息信息,默认第一个item为大图,注意,如果图文数超过10,则将会无响应
Title 图文消息标题
Description 图文消息描述
PicUrl 图片链接,支持JPG、PNG格式,较好的效果为大图360200,小图200200
Url 点击图文消息跳转链接

MsgTyp描述的是推送消息的类型,如text\image\voice\video\music\news等。

首先定义一个图文消息类型的XML包:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$newsTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<ArticleCount>2</ArticleCount>
<Articles>
<item>
<Title><![CDATA[欢迎关注superliar]]></Title>
<Description><![CDATA[superliar是一个真人秀节目,balabalabalabalabalabalabalabala]]></Description>
<PicUrl><![CDATA[http://i2.hdslb.com/bfs/archive/e4d44a24ef5b838db63ac6c4c5fda0302102fb23.jpg]]></PicUrl>
<Url><![CDATA[http://www.panda.tv/]]></Url>
</item>
<item>
<Title><![CDATA[玩狼人杀有什么独家技巧?]]></Title>
<Description><![CDATA[一个玩家做了什么不重要,重要的是要知道ta为什么这么做。]]></Description>
<PicUrl><![CDATA[http://i0.hdslb.com/bfs/archive/b957f527aadaddc3c32287f0ff5c1858df696658.jpg]]></PicUrl>
<Url><![CDATA[https://www.zhihu.com/question/25833846]]></Url>
</item>
</Articles>
</xml>";

然后将订阅的Event事件处理修改为:

1
2
3
4
5
6
7
8
9
if ($event == "subscribe") {
echo "订阅事件";
$msgType = "news";
$resultStr = sprintf($newsTpl, $fromUsername, $toUsername, $time, $msgType);
echo $resultStr;
}
elseif ($event == "unsubscribe") {
echo "取消订阅事件";
}

此时再重新关注,收到的就是一条图文消息了,其他类型的消息也是同样的原理。

关键字触发事件

关键字触发一般用于运营活动中,即用户发送一条特定的消息,服务器返回一条特定的消息。

返回文本消息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if(!empty( $keyword )) {
if ($keyword == "text") {
$msgType = "text";
$contentStr = "您发送了".$keyword;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
$msgType = "text";
$contentStr = "Hello World";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo "Input something...";
}

这时用户输入text,就会收到服务器返回的您发送了text。用户发送其他信息,则返回Hello World

返回图文消息

重新定义一个图文消息XML数据包:

1
2
3
4
5
6
7
8
9
10
11
12
13
$newsNoImgTpl = "<xml>
<ToUserName><![CDATA[%s]]></ToUserName>
<FromUserName><![CDATA[%s]]></FromUserName>
<CreateTime>%s</CreateTime>
<MsgType><![CDATA[%s]]></MsgType>
<ArticleCount>1</ArticleCount>
<Articles>
<item>
<Title><![CDATA[欢迎关注superliar]]></Title>
<Description><![CDATA[superliar是一个真人秀节目,balabalabalabalabalabalabalabala]]></Description>
<Url><![CDATA[http://www.panda.tv/]]></Url>
</Articles>
</xml>";

触发事件设置为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
if(!empty( $keyword )) {
if ($keyword == "text") {
$msgType = "text";
$contentStr = "您发送了".$keyword;
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
if ($keyword == "news") {
$msgType = "news";
$resultStr = sprintf($newsNoImgTpl, $fromUsername, $toUsername, $time, $msgType);
echo $resultStr;
}
$msgType = "text";
$contentStr = "Hello World";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}else{
echo "Input something...";
}

此时当用户发送news时,就会收到一条无图的图文消息。

接收不同类型消息

如果要接收处理不同类型的消息,首先要获取用户发送的消息类型:

1
$msgType = $postObj->MsgType;

此时可针对用户发送的不同类型的消息,进行对应的处理:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
if ($msgType == "image") {
$msgType = "text";
$contentStr = "您发送了image类型的消息,服务器返回text类型消息";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
elseif ($msgType == "voice") {
$msgType = "text";
$contentStr = "您发送了voice类型的消息,服务器返回text类型消息";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
elseif ($msgType == "video") {
$msgType = "text";
$contentStr = "您发送了video类型的消息,服务器返回text类型消息";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}
elseif ($msgType == "music") {
$msgType = "text";
$contentStr = "您发送了music类型的消息,服务器返回text类型消息";
$resultStr = sprintf($textTpl, $fromUsername, $toUsername, $time, $msgType, $contentStr);
echo $resultStr;
}

Demo下载请点击这里